from demo.init import db

'''
一对多关系：一Classe对多Student
db.relationship()关系函数定义关系属性，
这里让Classe指向Student类并加载多个，如果想要一对一关系，使用userlist=False,并设置给relationship()。

backref是在一个Student类上声明新属性的简单方法，也可以通过stu._class来获取该学生所属班级
lazy决定了SQLALCHEMY什么时候从数据库加载数据：
* select : 默认属性。按需加载，即在访问到属性的时候，才会全部加载该属性的数据
* joined : 加载记录，但使用联结
* subquery : 与joined类似，立即加载，但使用子查询。
* dynamic : 不加载记录，而是提供加载记录的查询，即生成一个query对象，方便进行条件过滤


'''
class Student(db.Model):
    __tablename__ = 'students'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), nullable=False)
    # 定义外键（表明.字段名）
    class_id = db.Column(db.Integer, db.ForeignKey('classes.id'))

    def __repr__(self):
        return '<Student: %r>' % self.name

class Classe(db.Model):
    __tablename__ = 'classes'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), nullable=False)
    # 使用关系函数定义关系属性,第一个参数为模型Student的名字，这是正向引用，Classe引用Student,
    students = db.relationship('Student', backref='_class', lazy='select')

    def __repr__(self):
        return '<Classe %r>' % self.name

# 创建所有的表
db.create_all()

# 删除Student表和Classe表的所有行
Student.query.delete()
Classe.query.delete()

# 创建数据，并插入数据库
stu1 = Student(name='stu1')
stu2 = Student(name='stu2')
stu3 = Student(name='stu3')

# 添加关系
class1 = Classe(name='class1', students=[stu1])
class2 = Classe(name='class2', students=[stu2, stu3])

db.session.add_all([stu1, stu2, stu3, class1, class2])
db.session.commit()

# 查询所有学生
stu_all = Student.query.all()
print('全部学生：', stu_all)

# 查询第一个学生所属班级
stu_01 = stu_all[0]
print("该学生所属班级：", stu_01._class)

# 查询二班所有的学生
stus_of_class2 = Student.query.filter_by(_class=class2).all()
print('二班的学生：', stus_of_class2)

# 查询全部班级
cls_all = Classe.query.all()
print('全部班级:', cls_all)

# 查询二班所有的学生
cls2 = Classe.query.filter_by(name='class2').first()
print('二班学生：', cls2.students)
